package com.tool.shiro.realm;

import com.tool.shiro.pojo.ShiroPermission;
import com.tool.shiro.pojo.ShiroRole;
import com.tool.shiro.pojo.ShiroUser;
import com.tool.shiro.salt.MyByteSource;
import com.tool.shiro.service.ShiroUserService;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import java.util.List;

/**
 * 自定义项目用户Realm
 * 项目需要自定义用户realm时继承该类
 * 注意: service层等定制化的类和方法、常量等需要自己写好改好后放进来并进行修改
 * 完全继承则数据库管理员表名默认为 user
 */
public class UserRealm extends AuthorizingRealm {

    @Autowired
    private ShiroUserService shiroUserService;

    /**
     * 授权信息
     * @param principalCollection       用户凭证信息
     * @return      授权信息
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        // 获取身份信息[account]
        String primaryPrincipal = (String) principalCollection.getPrimaryPrincipal();
        ShiroUser shiroUser = new ShiroUser();
        shiroUser.setAccount(primaryPrincipal);
        shiroUser = shiroUserService.queryUser(shiroUser);
        // 通过身份信息获取角色
        List<ShiroRole> shiroRoles = shiroUserService.queryRolesByUser(shiroUser);
        // 如果角色信息不为空,授权角色信息
        if(!CollectionUtils.isEmpty(shiroRoles)) {
            SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
            ShiroUser finalUser = shiroUser;
            shiroRoles.forEach(role -> {
                // 添加授权信息
                simpleAuthorizationInfo.addRole(role.getName());
                // 获取不同角色可用权限
                List<ShiroPermission> shiroPermissions = shiroUserService.queryPermissionsByUser(finalUser);
                // 如果权限集合不为空
                if (!CollectionUtils.isEmpty(shiroPermissions)) {
                    // 将权限集合循环添加到授权信息中
                    shiroPermissions.forEach(permission -> {
                        simpleAuthorizationInfo.addStringPermission(permission.getValue());
                    });
                }
            });
            return simpleAuthorizationInfo;
        }
        return null;
    }

    /**
     * 认证信息
     * @param authenticationToken       用户认证信息
     * @return      认证信息
     * @throws AuthenticationException  抛出认证错误
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        // 获取身份信息(用户登陆凭证[account])
        String principal = (String) authenticationToken.getPrincipal();
        ShiroUser shiroUser = new ShiroUser();
        shiroUser.setAccount(principal);
        // 通过登录凭证获取管理员信息
        shiroUser = shiroUserService.queryUser(shiroUser);
        // 如果管理员信息非空,返回认证信息
        if (!ObjectUtils.isEmpty(shiroUser)) {
            return new SimpleAuthenticationInfo(
                    shiroUser.getAccount(),
                    shiroUser.getPassword(),
                    new MyByteSource(shiroUser.getSalt()),
                    this.getName());
        }
        return null;
    }
}
